package com.hnx.admin.utils;


import cn.hutool.core.net.NetUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;

/*
项目名称： core
创 建 人: 倔强的头发
创建日期： 2025/5/29   18:12:11 
描   述：
*/
@Slf4j
public class IPUtil {
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST = "127.0.0.1";
    private final static String IP_V6_HOST  = "0:0:0:0:0:0:0:1";
    private static final List<String> HEADERS = Arrays.asList(
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_CLIENT_IP",
            "HTTP_X_FORWARDED_FOR",
            "X-Real-IP",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR"
    );
    public static String getClientIp(HttpServletRequest request) {
        return HEADERS.stream()
                .map(request::getHeader)
                .filter(ip -> ip != null && !ip.isEmpty() && !UNKNOWN.equalsIgnoreCase(ip))
                .findFirst()
                .map(ip -> {
                    if (ip.contains(",")) {
                        return ip.split(",")[0].trim();
                    }
                    return ip;
                })
                .orElse(IP_V6_HOST.equals(request.getRemoteAddr())?LOCALHOST:request.getRemoteAddr());
    }
    // IP验证正则表达式（包含IPv4和IPv6）

//    public static String resolveClientIp(HttpServletRequest request) {
//        String[] headers = {
//                "X-Forwarded-For",
//                "Proxy-Client-IP",
//                "WL-Proxy-Client-IP",
//                "HTTP_X_FORWARDED_FOR",
//                "HTTP_X_FORWARDED",
//                "HTTP_X_CLUSTER_CLIENT_IP",
//                "HTTP_CLIENT_IP",
//                "HTTP_FORWARDED_FOR",
//                "HTTP_FORWARDED",
//                "HTTP_VIA",
//                "REMOTE_ADDR"
//        };
//
//        for (String header : headers) {
//            String ip = request.getHeader(header);
//            if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
//                // 处理X-Forwarded-For多个IP的情况（取第一个非内部IP）
//                if (header.equalsIgnoreCase("X-Forwarded-For")) {
//                    String[] ips = ip.split(",");
//                    for (String candidate : ips) {
//                        candidate = candidate.trim();
//                        if (isValidPublicIp(candidate)) {
//                            return candidate;
//                        }
//                    }
//                } else if (isValidPublicIp(ip)) {
//                    return ip;
//                }
//            }
//        }
//
//        // 回退到remoteAddr
//        String remoteAddr = request.getRemoteAddr();
//        return isValidPublicIp(remoteAddr) ? remoteAddr : "127.0.0.1";
//    }

    public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
    public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
    public static boolean matchIP(String ip, List<String> ips){
        Integer len = ips.size();
        boolean flag = false;
        for(int i=0;i<len;i++){
            String ipi = ips.get(i);
            if(ipi.indexOf("/") >= 0){
                flag = NetUtil.isInRange(ip, ipi);
                if(flag) return true;
            }
            if(ipi.indexOf("-") >= 0 || ipi.indexOf("~") >=0){
                String[] split = ipi.split("-").length == 1? ipi.split("~"): ipi.split("-");
                String startIp = split[0];
                String endIp = split[1];
                long ipLong = NetUtil.ipv4ToLong(ip);
                long startIpLong = NetUtil.ipv4ToLong(startIp);
                long endIpLong = NetUtil.ipv4ToLong(endIp);
                flag = (ipLong >= startIpLong) && (ipLong <= endIpLong);
                if(flag) return true;
            }
            if(ipi.indexOf("*") >=0){
                flag = ipi.matches(REGX_IP_WILDCARD);
                if(flag) return true;
            }
            flag = ip.equals(ipi);
            if(flag) return true;
        }
        return flag;
    }
}
